unit eventeditorunit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Buttons,
  ExtCtrls, ComCtrls, LCLTranslator, EditBtn, Spin, languagehelper,
  eclistframeunit, fpjson, tilesetgraphicsunit;

const
  EVENT_ID_NEW = -1;

type

  { TEventEditorForm }

  TEventEditorForm = class(TForm)
    ApplyBitBtn: TBitBtn;
    ButtonAvailabilityTimer: TTimer;
    EventECListFrame: TECListFrame;
    ImageButton: TButton;
    RouteButton: TButton;
    CancelBitBtn: TBitBtn;
    PriorityComboBox: TComboBox;
    TriggerComboBox: TComboBox;
    PriorityGroupBox: TGroupBox;
    PassThroughCheckBox: TCheckBox;
    DirFixCheckBox: TCheckBox;
    TriggerGroupBox: TGroupBox;
    StepAnimCheckBox: TCheckBox;
    WalkAnimCheckBox: TCheckBox;
    OptionsGroupBox: TGroupBox;
    MoveFreqLabel: TLabel;
    MoveFreqComboBox: TComboBox;
    MoveSpeedLabel: TLabel;
    MoveSpeedComboBox: TComboBox;
    MoveTypeComboBox: TComboBox;
    MoveTypeLabel: TLabel;
    MovementGroupBox: TGroupBox;
    ImageGroupBox: TGroupBox;
    ItemCheckBox: TCheckBox;
    ActorCheckBox: TCheckBox;
    SelfSwitchComboBox: TComboBox;
    SelfSwitchCheckBox: TCheckBox;
    ItemComboBox: TComboBox;
    ActorComboBox: TComboBox;
    ImageSpeedButton: TSpeedButton;
    SettingsEcsSplitter: TSplitter;
    VarValueLabel: TLabel;
    VarValueSpinEdit: TSpinEdit;
    Switch2CheckBox: TCheckBox;
    Switch1EditButton: TEditButton;
    Switch1CheckBox: TCheckBox;
    ConditionsGroupBox: TGroupBox;
    OkBitBtn: TBitBtn;
    Panel1: TPanel;
    SettingsScrollBox: TScrollBox;
    SettingsPanel: TPanel;
    ResultBevel: TBevel;
    ClearPageBitBtn: TBitBtn;
    CopyPageBitBtn: TBitBtn;
    DeletePageBitBtn: TBitBtn;
    NameEdit: TEdit;
    NameLabel: TLabel;
    NewPageBitBtn: TBitBtn;
    NoteEdit: TEdit;
    NoteLabel: TLabel;
    PastePageBitBtn: TBitBtn;
    VarCheckBox: TCheckBox;
    Switch2EditButton: TEditButton;
    VarEditButton: TEditButton;
    PagesTabControl: TTabControl;
    TopPanel: TPanel;
    ResultPanel: TPanel;
    procedure ActorCheckBoxChange(Sender: TObject);
    procedure ApplyBitBtnClick(Sender: TObject);
    procedure ButtonAvailabilityTimerTimer(Sender: TObject);
    procedure ClearPageBitBtnClick(Sender: TObject);
    procedure CopyPageBitBtnClick(Sender: TObject);
    procedure DeletePageBitBtnClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure ImageButtonClick(Sender: TObject);
    procedure ItemCheckBoxChange(Sender: TObject);
    procedure MoveTypeComboBoxChange(Sender: TObject);
    procedure NewPageBitBtnClick(Sender: TObject);
    procedure OkBitBtnClick(Sender: TObject);
    procedure PagesTabControlChange(Sender: TObject);
    procedure PagesTabControlChanging(Sender: TObject; var AllowChange: Boolean
      );
    procedure PastePageBitBtnClick(Sender: TObject);
    procedure SelfSwitchCheckBoxChange(Sender: TObject);
    procedure Switch1CheckBoxChange(Sender: TObject);
    procedure Switch1EditButtonButtonClick(Sender: TObject);
    procedure Switch1EditButtonKeyPress(Sender: TObject; var Key: char);
    procedure Switch2CheckBoxChange(Sender: TObject);
    procedure Switch2EditButtonButtonClick(Sender: TObject);
    procedure Switch2EditButtonKeyPress(Sender: TObject; var Key: char);
    procedure VarCheckBoxChange(Sender: TObject);
    procedure UpdateButtonAvailability;
    procedure VarEditButtonButtonClick(Sender: TObject);
    procedure VarEditButtonKeyPress(Sender: TObject; var Key: char);
  private
    EventList: TJSONArray;
    EventId: Integer;

    Pages: TJSONArray;

    Switch1Id, Switch2Id, VarId: Integer;
    EventX, EventY: Integer;
    IsLoading: Boolean;

    TilesetGraphics: TTilesetGraphics;

    CharIndex, CharPattern, CharDir: Integer;
    CharFilename: String;
    TileId: Integer;
  public
    procedure EditEvent(AEventList: TJSONArray; AEventId: Integer; ATilesetGraphics: TTilesetGraphics = nil);
    procedure CreateNew(AEventList: TJSONArray; X, Y: Integer; ATilesetGraphics: TTilesetGraphics = nil); overload;
    procedure PresetPages;
    procedure SavePageChanges;
    procedure UpdatePage;
    function CreateEmptyPage: TJSONObject;
    procedure UpdateEditButtons;
    procedure PresetComboboxes;
    procedure LoadCharGraphics;
    procedure SaveEventData;
  end;

var
  EventEditorForm: TEventEditorForm;

implementation

uses
  comboboxhelper, globals, imageselection, namedindexselection, clipboardhelper;

resourcestring
  rsEventMovement_Fixed = 'Fixed';
  rsEventMovement_Random = 'Random';
  rsEventMovement_Approach = 'Approach';
  rsEventMovement_Custom = 'Custom';

  rsEventSpeed_1 = '1: 12.5%';
  rsEventSpeed_2 = '2: 25%';
  rsEventSpeed_3 = '3: 50%';
  rsEventSpeed_4 = '4: normal';
  rsEventSpeed_5 = '5: 200%';
  rsEventSpeed_6 = '6: 400%';

  rsEventFrequency_1 = '1: lowest';
  rsEventFrequency_2 = '2: low';
  rsEventFrequency_3 = '3: normal';
  rsEventFrequency_4 = '4: high';
  rsEventFrequency_5 = '5: highest';

  rsEventPriority_belowCharacters = 'Below char.';
  rsEventPriority_sameLevelAsCharacters = 'As char.';
  rsEventPriority_overCharacters = 'Over char.';

  rsEventTrigger_actionButton = 'Action button';
  rsEventTrigger_playerTouch = 'Player touch';
  rsEventTrigger_eventTouch = 'Event touch';
  rsEventTrigger_autorun = 'Autorun';
  rsEventTrigger_parallelProcess = 'Parallel';



{$R *.lfm}

{ TEventEditorForm }

procedure TEventEditorForm.PagesTabControlChange(Sender: TObject);
begin
  UpdatePage;
end;

procedure TEventEditorForm.PagesTabControlChanging(Sender: TObject;
  var AllowChange: Boolean);
begin
  if not IsLoading and (Pages <> nil) then
     SavePageChanges;
end;

procedure TEventEditorForm.PastePageBitBtnClick(Sender: TObject);
var
  PastedObject: TJSONObject;
  TypeString: String;
  PlaceOfNewTab: Integer;
begin
  TypeString := DataTypeStrings[DATA_TYPE_ID_MAP_EVENT_PAGE];
  if ClipboardHasData(TypeString) then begin
    PastedObject := GetJsonObjectFromClipboard(TypeString);
    if PastedObject <> nil then begin
       IsLoading := True;

       SavePageChanges;

       PlaceOfNewTab := PagesTabControl.TabIndex + 1;
       Pages.Insert(PlaceOfNewTab, PastedObject);
       PagesTabControl.Tabs.Add(IntToStr(PagesTabControl.Tabs.Count + 1));
       PagesTabControl.TabIndex := PlaceOfNewTab;

       UpdatePage;
       UpdateButtonAvailability;

       IsLoading := False;
    end;
  end;
end;

procedure TEventEditorForm.ItemCheckBoxChange(Sender: TObject);
begin
  ItemComboBox.Enabled := ItemCheckBox.Checked;
  if ItemComboBox.Enabled then begin
     FillDbArrayComboBox(ItemComboBox, Game.Db.Items);
     if ItemComboBox.ItemIndex < 0 then
        ItemComboBox.ItemIndex := 0;
  end;
end;

procedure TEventEditorForm.MoveTypeComboBoxChange(Sender: TObject);
begin
  RouteButton.Enabled := MoveTypeComboBox.ItemIndex = 3;
end;

procedure TEventEditorForm.NewPageBitBtnClick(Sender: TObject);
var
  PlaceOfNewTab: Integer;
begin
  IsLoading := True;

  SavePageChanges;

  PlaceOfNewTab := PagesTabControl.TabIndex + 1;
  Pages.Insert(PlaceOfNewTab, CreateEmptyPage);
  PagesTabControl.Tabs.Add(IntToStr(PagesTabControl.Tabs.Count + 1));
  PagesTabControl.TabIndex := PlaceOfNewTab;

  UpdatePage;
  UpdateButtonAvailability;

  IsLoading := False;
end;

procedure TEventEditorForm.OkBitBtnClick(Sender: TObject);
begin
  SaveEventData
end;

procedure TEventEditorForm.ActorCheckBoxChange(Sender: TObject);
begin
  ActorComboBox.Enabled := ActorCheckBox.Checked;
  if ActorComboBox.Enabled then begin
     FillDbArrayComboBox(ActorComboBox, Game.Db.Actors);
     if ActorComboBox.ItemIndex < 0 then
        ActorComboBox.ItemIndex := 0;
  end;
end;

procedure TEventEditorForm.ApplyBitBtnClick(Sender: TObject);
begin
  SaveEventData;
end;

procedure TEventEditorForm.ButtonAvailabilityTimerTimer(Sender: TObject);
begin
  if (Pages <> nil) then
     UpdateButtonAvailability;
end;

procedure TEventEditorForm.ClearPageBitBtnClick(Sender: TObject);
begin
  IsLoading := True;

  Pages[PagesTabControl.TabIndex] := CreateEmptyPage;

  UpdatePage;
  UpdateButtonAvailability;

  IsLoading := False;
end;

procedure TEventEditorForm.CopyPageBitBtnClick(Sender: TObject);
var
  Page: TJSONObject;
begin
  SavePageChanges;

  Page := Pages.Objects[PagesTabControl.TabIndex];
  if (Page <> nil) then
    CopyDataToClipboard(DataTypeIds[DATA_TYPE_ID_MAP_EVENT_PAGE], Page);

  UpdateButtonAvailability
end;

procedure TEventEditorForm.DeletePageBitBtnClick(Sender: TObject);
begin
  if Pages.Count < 2 then
     Exit;

  IsLoading := True;

  Pages.Delete(PagesTabControl.TabIndex);
  if PagesTabControl.TabIndex >= Pages.Count then
     PagesTabControl.TabIndex := Pages.Count - 1;
  PagesTabControl.Tabs.Delete(Pages.Count);
  UpdatePage;

  UpdateButtonAvailability;

  IsLoading := False;
end;

procedure TEventEditorForm.FormClose(Sender: TObject;
  var CloseAction: TCloseAction);
begin
  ImageSpeedButton.Glyph.Clear;
  EventECListFrame.SetDatabase(nil);
  EventECListFrame.SetList(nil);
end;

procedure TEventEditorForm.ImageButtonClick(Sender: TObject);
begin
  //TODO
  if ImageSelectionForm.ShowFullCharSelection(CharFilename, CharIndex,
                                                            CharPattern,
                                                            CharDir,
                                                            TileId,
                                                            TilesetGraphics)
  then begin
    CharFilename := ImageSelectionForm.SelectedFilename;
    CharIndex := ImageSelectionForm.Index;
    CharDir := ImageSelectionForm.Direction;
    CharPattern := ImageSelectionForm.Pattern;
    TileId := ImageSelectionForm.TileId;
    LoadCharGraphics;
  end;
end;

procedure TEventEditorForm.SelfSwitchCheckBoxChange(Sender: TObject);
begin
  SelfSwitchComboBox.Enabled := SelfSwitchCheckBox.Checked;
  if SelfSwitchComboBox.Enabled then begin
    FillUserSelfSwitchNameCombobox(SelfSwitchComboBox);
     if SelfSwitchComboBox.ItemIndex < 0 then
        SelfSwitchComboBox.ItemIndex := 0;
  end;
end;

procedure TEventEditorForm.Switch1CheckBoxChange(Sender: TObject);
begin
  Switch1EditButton.Enabled := Switch1CheckBox.Checked;
end;

procedure TEventEditorForm.Switch1EditButtonButtonClick(Sender: TObject);
begin
  Switch1Id := NamedIndexSelectionForm.SelectSwitch(Switch1Id, Game.Db);
  UpdateEditButtons
end;

procedure TEventEditorForm.Switch1EditButtonKeyPress(Sender: TObject;
  var Key: char);
begin
  Key := #0;
  Switch1EditButtonButtonClick(Sender);
end;

procedure TEventEditorForm.Switch2CheckBoxChange(Sender: TObject);
begin
  Switch2EditButton.Enabled := Switch2CheckBox.Checked;
end;

procedure TEventEditorForm.Switch2EditButtonButtonClick(Sender: TObject);
begin
  Switch2Id := NamedIndexSelectionForm.SelectSwitch(Switch2Id, Game.Db);
  UpdateEditButtons
end;

procedure TEventEditorForm.Switch2EditButtonKeyPress(Sender: TObject;
  var Key: char);
begin
  Key := #0;
  Switch2EditButtonButtonClick(Sender);
end;

procedure TEventEditorForm.VarCheckBoxChange(Sender: TObject);
begin
  VarEditButton.Enabled := VarCheckBox.Checked;
  VarValueSpinEdit.Enabled := VarCheckBox.Checked;
end;

procedure TEventEditorForm.UpdateButtonAvailability;
begin
  if Pages = nil then
     Exit;

  DeletePageBitBtn.Enabled := Pages.Count > 1;
  PastePageBitBtn.Enabled := ClipboardHasData(DataTypeStrings[DATA_TYPE_ID_MAP_EVENT_PAGE]);
end;

procedure TEventEditorForm.VarEditButtonButtonClick(Sender: TObject);
begin
  VarId := NamedIndexSelectionForm.SelectVariable(VarId, Game.Db);
  UpdateEditButtons
end;

procedure TEventEditorForm.VarEditButtonKeyPress(Sender: TObject; var Key: char
  );
begin
  Key := #0;
  VarEditButtonButtonClick(Sender);
end;

procedure TEventEditorForm.EditEvent(AEventList: TJSONArray; AEventId: Integer;
  ATilesetGraphics: TTilesetGraphics);
var
  Event: TJSONObject;

  procedure PresetFields;
  var
    NameJson, NoteJson: TJSONString;
    EventName: String = '';
    Note: String = '';
  begin
    if Event.Find('name', NameJson) then
       EventName := NameJson.AsString;

    if Event.Find('note', NoteJson) then
       Note := NoteJson.AsString;

    NameEdit.Text := EventName;
    NoteEdit.Text := Note;
  end;

begin
  IsLoading := True;
  EventList := AEventList;
  EventId := AEventId;

  Event := EventList.Objects[EventId];
  EventX := Event.Integers['x'];
  EventY := Event.Integers['y'];
  TilesetGraphics := ATilesetGraphics;

  PresetComboboxes;

  PresetFields;

  if Pages <> nil then
     FreeAndNil(Pages);
  Pages := Event.Arrays['pages'].Clone as TJSONArray;

  PresetPages;
  UpdateButtonAvailability;
  PagesTabControl.TabIndex := 0;
  UpdatePage;

  IsLoading := False;
  ShowModal
end;

procedure TEventEditorForm.CreateNew(AEventList: TJSONArray; X, Y: Integer;
  ATilesetGraphics: TTilesetGraphics);
begin
  IsLoading := True;
  EventList := AEventList;
  EventId := EventList.Count;
  EventX := X;
  EventY := Y;
  TilesetGraphics := ATilesetGraphics;

  NameEdit.Text := 'EV%.3d'.Format([EventList.Count]);
  NoteEdit.Text := '';
  PresetComboboxes;

  if Pages <> nil then
     FreeAndNil(Pages);
  Pages := TJSONArray.Create([
        CreateEmptyPage
  ]);

  PresetPages;
  UpdateButtonAvailability;
  PagesTabControl.TabIndex := 0;
  UpdatePage;

  MoveTypeComboBox.ItemHeight := 0;
  MoveSpeedComboBox.ItemHeight := 4;
  MoveFreqComboBox.ItemHeight := 4;
  PriorityComboBox.ItemHeight := 0;
  TriggerComboBox.ItemIndex := 0;

  IsLoading := False;
  ShowModal;
end;

procedure TEventEditorForm.PresetPages;
var
  I: Integer;
begin
  with PagesTabControl.Tabs do begin
    BeginUpdate;
    Clear;
    for I := 1 to Pages.Count do
      Add(IntToStr(I));
    EndUpdate;
  end;
end;

procedure TEventEditorForm.SavePageChanges;
var
  Page: TJSONObject;

  procedure SaveConditions;
  var
    C: TJSONObject;
  begin
    C := Page.Objects['conditions'];
    C.Booleans['switch1Valid'] := Switch1CheckBox.Checked;
    C.Integers['switch1Id'] := Switch1Id;
    C.Booleans['switch2Valid'] := Switch2CheckBox.Checked;
    C.Integers['switch2Id'] := Switch2Id;
    C.Booleans['variableValid'] := VarCheckBox.Checked;
    C.Integers['variableId'] := VarId;
    C.Integers['variableValue'] := VarValueSpinEdit.Value;
    C.Booleans['selfSwitchValid'] := SelfSwitchCheckBox.Checked;
    C.Strings['selfSwitchCh'] := Chr(Ord('A') + SelfSwitchComboBox.ItemIndex);
    C.Booleans['itemValid'] := ItemCheckBox.Checked;
    C.Integers['itemId'] := ItemComboBox.ItemIndex + 1;
    C.Booleans['actorValid'] := ActorCheckBox.Checked;
    C.Integers['actorId'] := ActorComboBox.ItemIndex + 1;
  end;

  procedure SaveMoveSettings;
  begin
    Page.Integers['moveType'] := MoveTypeComboBox.ItemIndex;
    //TODO: movement route
    Page.Integers['moveSpeed'] := MoveSpeedComboBox.ItemIndex;
    Page.Integers['moveFrequency'] := MoveFreqComboBox.ItemIndex;
  end;

  procedure SaveOptions;
  begin
    Page.Booleans['walkAnime'] := WalkAnimCheckBox.Checked;
    Page.Booleans['stepAnime'] := StepAnimCheckBox.Checked;
    Page.Booleans['directionFix'] := DirFixCheckBox.Checked;
    Page.Booleans['through'] := PassThroughCheckBox.Checked;
  end;

  procedure SaveGraphics;
  var
    I: TJSONObject;
  begin
    I := Page.Objects['image'];
    I.Integers['characterIndex'] := CharIndex;
    I.Strings['characterName'] := CharFilename;
    I.Integers['direction'] := CharDir;
    I.Integers['pattern'] := CharPattern;
    I.Integers['tileId'] := TileId;
  end;

begin
  Page := Pages.Objects[PagesTabControl.TabIndex];

  SaveConditions;
  SaveGraphics;
  SaveMoveSettings;
  SaveOptions;
  Page.Integers['priorityType'] := PriorityComboBox.ItemIndex;
  Page.Integers['trigger'] := TriggerComboBox.ItemIndex;
end;

procedure TEventEditorForm.UpdatePage;
var
  Page: TJSONObject;

  procedure UpdateConditions;
  var
    C: TJSONObject;
  begin
    C := Page.Objects['conditions'];

    Switch1CheckBox.Checked := C.Booleans['switch1Valid'];
    Switch1Id := C.Integers['switch1Id'];
    Switch2CheckBox.Checked := C.Booleans['switch2Valid'];
    Switch2Id := C.Integers['switch2Id'];
    VarCheckBox.Checked := C.Booleans['variableValid'];
    VarId := C.Integers['variableId'];
    VarValueSpinEdit.Value := C.Integers['variableValue'];
    SelfSwitchCheckBox.Checked := C.Booleans['selfSwitchValid'];
    if C.Strings['selfSwitchCh'] <> '' then
      SelfSwitchComboBox.ItemIndex := Ord(C.Strings['selfSwitchCh'][1]) - Ord('A');
    ItemCheckBox.Checked := C.Booleans['itemValid'];
    ItemComboBox.ItemIndex := C.Integers['itemId'] - 1;
    ActorCheckBox.Checked := C.Booleans['actorValid'];
    ActorComboBox.ItemIndex := C.Integers['actorId'] - 1;

    UpdateEditButtons;
    {TODO: update names}
  end;

  procedure UpdateGraphics;
  var
    I: TJSONObject;
  begin
    I := Page.Objects['image'];

    CharIndex := I.Integers['characterIndex'];
    CharFilename := I.Strings['characterName'];
    CharDir := I.Integers['direction'];
    CharPattern := I.Integers['pattern'];
    TileId := I.Integers['tileId'];
    LoadCharGraphics;
  end;

  procedure UpdateMove;
  begin
    MoveTypeComboBox.ItemIndex := Page.Integers['moveType'];
    //TODO: movement route
    MoveSpeedComboBox.ItemIndex := Page.Integers['moveSpeed'];
    MoveFreqComboBox.ItemIndex := Page.Integers['moveFrequency'];
  end;

  procedure UpdateOptions;
  begin
    WalkAnimCheckBox.Checked := Page.Booleans['walkAnime'];
    StepAnimCheckBox.Checked := Page.Booleans['stepAnime'];
    DirFixCheckBox.Checked := Page.Booleans['directionFix'];
    PassThroughCheckBox.Checked := Page.Booleans['through'];
  end;

begin
  if Pages = nil then
     Exit;

  Page := Pages.Objects[PagesTabControl.TabIndex];
  UpdateConditions;
  UpdateGraphics;
  UpdateMove;
  UpdateOptions;

  PriorityComboBox.ItemIndex := Page.Integers['priorityType'];
  TriggerComboBox.ItemIndex := Page.Integers['trigger'];

  EventECListFrame.SetDatabase(Game.Db);
  EventECListFrame.SetList(Page.Arrays['list']);

  {TODO: update event command list}
end;

function TEventEditorForm.CreateEmptyPage: TJSONObject;
begin
  Result := TJSONObject.Create([
    'conditions', TJSONObject.Create([
      'actorId', 1,
      'actorValid', false,
      'itemId', 1,
      'itemValid', false,
      'selfSwitchCh', 'A',
      'selfSwitchValid', false,
      'switch1Id', 1,
      'switch1Valid', false,
      'switch2Id', 1,
      'switch2Valid', false,
      'variableId', 1,
      'variableValid', false,
      'variableValue', 0
    ]),
    'directionFix', false,
    'image', TJSONObject.Create([
      'tileId', 0,
      'characterName', '',
      'direction', 4,
      'pattern', 1,
      'characterIndex', 0
    ]),
    'list', TJSONArray.Create([
      TJSONObject.Create([
        'code', 0,
        'indent', 0,
        'parameters', TJSONArray.Create()
      ])
    ]),
    'moveFrequency', 3,
    'moveRoute', TJSONObject.Create([
       'list', TJSONArray.Create([
          TJSONObject.Create([
            'code', 0,
            'parameters', TJSONArray.Create()
          ])
       ]),
       'repeat', True,
       'skippable', False,
       'wait', False
    ]),
    'moveSpeed', 3,
    'moveType', 0,
    'priorityType', 1,
    'stepAnime', False,
    'through', False,
    'trigger', 0,
    'walkAnime', True
  ]);
end;

procedure TEventEditorForm.UpdateEditButtons;
begin
  Switch1EditButton.Text := Game.Db.GetSwitchName(Switch1Id);
  Switch2EditButton.Text := Game.Db.GetSwitchName(Switch2Id);
  VarEditButton.Text := Game.Db.GetVariableName(VarId);
end;

procedure TEventEditorForm.PresetComboboxes;
begin
  ItemComboBox.Items.Clear;
  ActorComboBox.Items.Clear;

  with MoveTypeComboBox.Items do begin
    BeginUpdate;
    Clear;
    Add(rsEventMovement_Fixed);
    Add(rsEventMovement_Random);
    Add(rsEventMovement_Approach);
    Add(rsEventMovement_Custom);
    EndUpdate;
  end;
  MoveTypeComboBox.ItemHeight := 0;

  with MoveSpeedComboBox.Items do begin
    BeginUpdate;
    Clear;
    Add(rsEventSpeed_1);
    Add(rsEventSpeed_2);
    Add(rsEventSpeed_3);
    Add(rsEventSpeed_4);
    Add(rsEventSpeed_5);
    Add(rsEventSpeed_6);
    EndUpdate;
  end;
  MoveSpeedComboBox.ItemHeight := 4;

  with MoveFreqComboBox.Items do begin
    BeginUpdate;
    Clear;
    Add(rsEventFrequency_1);
    Add(rsEventFrequency_2);
    Add(rsEventFrequency_3);
    Add(rsEventFrequency_4);
    Add(rsEventFrequency_5);
    EndUpdate;
  end;
  MoveFreqComboBox.ItemHeight := 4;

  with PriorityComboBox.Items do begin
    BeginUpdate;
    Clear;
    Add(rsEventPriority_belowCharacters);
    Add(rsEventPriority_sameLevelAsCharacters);
    Add(rsEventPriority_overCharacters);
    EndUpdate;
  end;
  PriorityComboBox.ItemHeight := 0;

  with TriggerComboBox.Items do begin
    BeginUpdate;
    Clear;
    Add(rsEventTrigger_actionButton);
    Add(rsEventTrigger_playerTouch);
    Add(rsEventTrigger_eventTouch);
    Add(rsEventTrigger_autorun);
    Add(rsEventTrigger_parallelProcess);
    EndUpdate;
  end;
  TriggerComboBox.ItemIndex := 0;
end;

procedure TEventEditorForm.LoadCharGraphics;
var
  Png: TBitmap;
begin
  ImageSpeedButton.Glyph.Clear;

  if CharFilename <> '' then begin
    Png := Game.GetCharacterGraphics(CharFilename, CharIndex, CharDir, CharPattern);
    ImageSpeedButton.Glyph.Assign(Png);
    Png.Free;
  end else if TilesetGraphics <> nil then begin
    Png := TilesetGraphics.GetUpperTile(TileId);
    if Png <> nil then begin
       ImageSpeedButton.Glyph.Assign(Png);
       Png.Free;
    end;
  end;
  {TODO: show tile graphics}
end;

procedure TEventEditorForm.SaveEventData;
var
  NewEvent: TJSONObject;
begin
  SavePageChanges;

  NewEvent := TJSONObject.Create([
    'id', EventId,
    'name', NameEdit.Text,
    'note', NoteEdit.Text,
    'pages', Pages.Clone as TJSONArray,
    'x', EventX,
    'y', EventY
  ]);

  if EventId >= EventList.Count then
     EventList.Add(NewEvent)
  else
    EventList.Objects[EventId] := NewEvent;
  Game.MapIsDirty := True;
end;

end.

